package user

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"private-domain-overseas-service/app/business/api/internal/repository/system"
	"private-domain-overseas-service/app/business/api/internal/repository/user"
	"private-domain-overseas-service/app/business/api/internal/svc"
	"private-domain-overseas-service/app/business/api/internal/types"
	"private-domain-overseas-service/pkg/constant"
	"private-domain-overseas-service/pkg/status/bizsystemsmsrecord"
	"private-domain-overseas-service/pkg/status/bizuser"
	"private-domain-overseas-service/pkg/xerr"
	"private-domain-overseas-service/tools/ent"
	"private-domain-overseas-service/tools/ent/hzsystemsmsrecord"
	"private-domain-overseas-service/tools/ent/hzusersurvey"
	"private-domain-overseas-service/tools/ent/predicate"
	"strconv"
	"time"
)

type UserSurveyLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewUserSurveyLogic - 用户问卷
func NewUserSurveyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserSurveyLogic {
	return &UserSurveyLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *UserSurveyLogic) UserSurvey(req *types.UserSurveyRequest) (resp *types.UserSurveyResponse, err error) {
	// 创建实例
	userSurveyDao := user.NewUserSurveyDao(l.ctx, l.svcCtx)
	captchaDao := system.NewSystemSmsRecordDao(l.ctx, l.svcCtx)

	// 剩余订购数量
	var orderLeave int64
	// 是否超过限额(默认返回false)
	var orderStatus bool
	// 用户为定向用户时候后台记录
	var directionalFirstInfo *ent.HzUserSurvey
	// 定向用户和普通用户份额hash取值
	hashFiled := constant.UserSurveyOrder
	// 返回值名称
	userSurveyName := req.UserSurveyName

	// 判断用户类型，如果为定向用户，则需要进行短信验证且存在于后台(不可重复订购)
	if req.UserSurveyType == bizuser.UserTypeDirectional {

		// 获取万能验证码
		universalCaptcha, _ := l.svcCtx.BizRedis.Hget(constant.HzAdminSystemConfigKey, constant.HzSystemSmsUniversal)

		// 验证短信验证码
		if req.UserSurveyCaptcha != universalCaptcha {
			// 获取验证码
			systemSmsConditions := make([]predicate.HzSystemSmsRecord, 0)
			systemSmsConditions = append(systemSmsConditions, hzsystemsmsrecord.SystemSmsPhoneEQ(req.UserSurveyPhone))
			systemSmsConditions = append(systemSmsConditions, hzsystemsmsrecord.SystemSmsExpireAtGTE(time.Now().Unix()))
			captchaInfo, errSms := captchaDao.SystemSmsRecordConditionsFirst(systemSmsConditions)
			if errSms != nil || captchaInfo == nil {
				return nil, xerr.ErrCodeMsg(xerr.ServerDataNotFoundError, fmt.Sprintf("未找到符合条件的验证码 %s", errSms))
			}

			// 校验验证码
			if captchaInfo.SystemSmsCaptcha != req.UserSurveyCaptcha {
				return nil, xerr.ErrCodeMsg(xerr.ServerApiCaptchaError, "校验验证码失败")
			}

			// 协程处理修改验证码信息
			go func() {
				defer func() {
					if r := recover(); r != nil {
						logx.Errorf("修改验证码信息失败 goroutine panic: %v", r)
					}
				}()
				err = l.handlerUpdateSystemSmsRecordStatus(captchaInfo.ID)
				if err != nil {
					logx.Errorf("修改验证码信息失败：%v", err)
				}
			}()
		}

		// 判断是否存在于后台(且未购买过订单)
		userSurveyConditions := make([]predicate.HzUserSurvey, 0)
		userSurveyConditions = append(userSurveyConditions, hzusersurvey.UserSurveyPhoneEQ(req.UserSurveyPhone))
		userSurveyConditions = append(userSurveyConditions, hzusersurvey.UserSurveyTypeEQ(bizuser.UserTypeDirectional))
		directionalFirstInfo, _ = userSurveyDao.UserSurveyConditionsFirst(userSurveyConditions)
		if directionalFirstInfo == nil {
			return nil, xerr.ErrCodeMsg(xerr.ServerDataNotFoundError, fmt.Sprintf("手机号未注册"))
		}
		if directionalFirstInfo.UserSurveyOrderNum != 0 {
			return nil, xerr.ErrCodeMsg(xerr.ServerDataRepeatError, fmt.Sprintf("手机号购买过订单"))
		}

		// 配置hash值
		hashFiled = constant.UserSurveyDirectional

		// 返回值名称
		userSurveyName = directionalFirstInfo.UserSurveyName
	}

	// 直接先从redis中取出剩余数,如果已经为0了则不在进行判断和剩余数修改
	value, err := l.svcCtx.BizRedis.Hget(constant.HzAdminSystemConfigKey, hashFiled)
	if err != nil {
		return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("获取redis中剩余订购数量失败: %v", err.Error()))
	}
	// redis获取到的值转int64
	userSurveyValue, _ := strconv.ParseInt(value, 10, 64)

	// 判断剩余数量是否大于0，大于0则处理
	if userSurveyValue > 0 {
		// 比对订购数量是否超出限额
		if req.UserSurveyOrderNum > userSurveyValue {
			orderStatus = true
		}

		// 计算剩余数量，如果不足，则扣掉已有份数
		orderLeave = userSurveyValue - req.UserSurveyOrderNum
		if orderLeave < 0 {
			orderLeave = 0
		}

		// 修改redis中剩余订购数量
		err = l.svcCtx.BizRedis.Hset(constant.HzAdminSystemConfigKey, hashFiled, strconv.FormatInt(orderLeave, 10))
		if err != nil {
			return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("修改redis中剩余订购数量失败: %v", err.Error()))
		}
	}

	// 剩余数已经为0,默认超出限额
	if userSurveyValue == 0 {
		orderStatus = true
	}

	// 组装添加用户问卷参数
	userSurveyInfo := &ent.HzUserSurvey{
		UserSurveyPhone:    req.UserSurveyPhone,
		UserSurveyName:     req.UserSurveyName,
		UserSurveySex:      req.UserSurveySex,
		UserSurveyType:     req.UserSurveyType,
		UserSurveyOrderNum: req.UserSurveyOrderNum,
		UpdateAt:           time.Now().Unix(),
	}

	// 定向问卷邀请
	if req.UserSurveyType == bizuser.UserTypeDirectional && directionalFirstInfo != nil {
		userSurveyInfo.ID = directionalFirstInfo.ID
		if err = userSurveyDao.UserSurveyUpdate(userSurveyInfo, nil); err != nil {
			return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("修改定向用户问卷失败: %v", err))
		}
	}

	// 普通问卷邀请
	if req.UserSurveyType == bizuser.UserTypeOrdinary {
		userSurveyInfo.CreatedAt = time.Now().Unix()
		if err = userSurveyDao.UserSurveyCreate(userSurveyInfo, nil); err != nil {
			return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("添加用户问卷失败: %v", err))
		}
	}

	// 组装返回数据
	resp = &types.UserSurveyResponse{
		UserSurveyName:           userSurveyName,
		IsOverUserSurveyOrderNum: orderStatus,
		UserSurveyOrderLeave:     orderLeave,
	}

	return resp, nil
}

// handlerUpdateSystemSmsRecordStatus - 修改验证码状态为已使用
func (l *UserSurveyLogic) handlerUpdateSystemSmsRecordStatus(ID int) error {
	// 创建实例
	captchaDao := system.NewSystemSmsRecordDao(l.ctx, l.svcCtx)

	// 组装参数
	smsUpdateStatusConditions := make([]predicate.HzSystemSmsRecord, 0)
	smsUpdateStatusConditions = append(smsUpdateStatusConditions, hzsystemsmsrecord.IDEQ(ID))
	captchaUpdateStatus := &ent.HzSystemSmsRecord{
		SystemSmsStatus: bizsystemsmsrecord.SmsStatusUse,
		UpdateAt:        time.Now().Unix(),
	}

	// 修改数据库
	err := captchaDao.SystemSmsRecordUpdateStatusByConditions(smsUpdateStatusConditions, captchaUpdateStatus, nil)
	if err != nil {
		fmt.Printf("修改验证码状态失败%s", err.Error())
		return err
	}

	return nil
}
